﻿//_______________________________________________________________________________________________________________________
// Copy Right (c) 2010, 2011 SapiensIT Consulting GmbH, all rights reserved
//_______________________________________________________________________________________________________________________
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT
// NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//_______________________________________________________________________________________________________________________
// PROJECT:     sapiens.at.SharePoint.LookupPicker (SharePoint 2010/V4)
//_______________________________________________________________________________________________________________________
// VERSION:     2.0
//_______________________________________________________________________________________________________________________
// DESCRIPTION: 
//_______________________________________________________________________________________________________________________
// LICENSE:     Different licens Types apply to different file types:
//               - Source code files are governed by the MICROSOFT PUBLIC LICENSE (Ms-PL)
//               - Binary files are governed by MSDN CODE GALLERY BINARY LICENSE
//               - Documentation files are governed by CREATIVE COMMONS ATTRIBUTION 3.0 LICENSE
//
//               The licenses can be found at the projects source location.
//               If you do not agree, don't use it!
// 
//_______________________________________________________________________________________________________________________
// Start SharePoint Branding, visit http://www.cliggin.com! Visit us on http://www.sapiens.at! Tell your friends! 
//_______________________________________________________________________________________________________________________
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using System.Threading;
using Microsoft.SharePoint.Security;
using System.Security.Permissions;
using System.Reflection;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Utilities;
using System.Globalization;

namespace Sapiens.at.SharePoint.Fields
{
    /// <summary>
    /// A lookup field that uses a picker control instead of the dropdown or the two lists (multi).
    /// </summary>
    /// <seealso cref="Sapiens.SharePoint.Controls.LookupPicker"/>
    /// <seealso cref="Sapiens.SharePoint.Controls.LookupPickerDialog"/>
    /// <seealso cref="Sapiens.SharePoint.Controls.LookupPickerFieldControl"/>
    /// <seealso cref="Sapiens.SharePoint.Controls.LookupPickerFieldEditor"/>
    /// <seealso cref="Sapiens.SharePoint.Controls.LookupPickerQueryControl"/>
    [SharePointPermissionAttribute(SecurityAction.Demand, ObjectModel = true)]
    public class LookupPickerField : SPFieldLookup
    {
        /// <summary>
        /// Gets the id of the lookup list
        /// </summary>
        public Guid LookupListId
        {
            get
            {
                try
                {
                    return new Guid(LookupList);
                }
                catch (FormatException exc)
                {
                    var web = SPContext.Current.Site.OpenWeb(LookupWebId);
                    if (web == null) { web = SPContext.Current.Web; }
                    SPList list = null;
                    try
                    {
                        list = web.GetList(LookupList);
                    }
                    catch
                    {
                        try
                        {
                            list = web.GetList(string.Concat(web.Url, "/", LookupList));
                        }
                        catch { }
                    }
                    if (list == null) { return Guid.Empty; }
                    LookupListId = list.ID;
                    web.Dispose();
                    return list.ID;
                }
            }
            set
            {
                SetFieldAttribute("List", "");
                LookupList = value.ToString();
                this.Update();
            }
        }

        public Guid LookupWebId
        {
            get
            {
                var webId = GetFieldAttribute("WebId");
                try
                {
                    return new Guid(webId);
                }
                catch (FormatException exc)
                {
                    var listId = GetFieldAttribute("List");
                    var web = SPContext.Current.Site.OpenWeb(listId);
                    if (web == null) { web = SPContext.Current.Web; }
                    try
                    {
                        var list = web.GetList(listId);
                        if (list != null) { LookupListId = list.ID; }
                        base.LookupWebId = web.ID;
                    }
                    catch
                    {
                        base.LookupWebId = base.LookupWebId;
                    }
                    this.Update();
                    web.Dispose();
                    return base.LookupWebId;
                }
            }
            set
            {
                base.LookupWebId = value;
            }
        }
        
        /// <summary>
        /// Gets or sets whether multiple lookup values are allowed in one field.
        /// </summary>
        public override bool AllowMultipleValues
        {
            get
            {
                return base.AllowMultipleValues;
            }
            set
            {
                base.AllowMultipleValues = value;
                SetFieldAttribute("Type", "LookupPicker");
            }
        }

        /// <summary>
        /// Gets or sets whether the dialog returns the whole list if no search text is entered.
        /// </summary>
        public bool AllowShowAll
        {
            get
            {
                var attribute = GetFieldAttribute("AllowShowAll");
                return string.IsNullOrEmpty(attribute) ? false : bool.Parse(attribute);
            }
            set
            {
                SetFieldAttribute("AllowShowAll", value.ToString());
            }
        }

        /// <summary>
        /// Gets or sets the name of the fields that will be searched in addition to the lookup field
        /// </summary>
        public string[] AdditionalSearchFields
        {
            get
            {
                var result = GetFieldAttribute("AdditionalSearchFields");
                if (result != null && !string.IsNullOrEmpty(result.ToString()))
                {
                    return result.ToString().Split(';', ',', ' ');
                }
                return new string[0];
            }
            set
            {
                string v = "";
                if (value != null)
                {
                    v = String.Join(";", value);
                }
                SetFieldAttribute("AdditionalSearchFields", v);
            }
        }

        /// <summary>
        /// Gets or sets the name of the fields that will be displayed in addition to the lookup field
        /// </summary>
        public string[] AdditionalDisplayFields
        {
            get
            {
                var result = GetFieldAttribute("AdditionalDisplayFields");
                if (result != null && !string.IsNullOrEmpty(result.ToString()))
                {
                    return result.ToString().Split(';', ',', ' ');
                }
                return new string[0];
            }
            set
            {
                string v = "";
                if (value != null)
                {
                    v = String.Join(";", value);
                }
                SetFieldAttribute("AdditionalDisplayFields", v);
            }
        }

        /// <summary>
        /// Gets or sets the content types that will return for a query
        /// </summary>
        public string[] ContentTypes
        {
            get
            {
                var result = GetFieldAttribute("ContentTypes");
                if (result != null && !string.IsNullOrEmpty(result.ToString()))
                {
                    return result.ToString().Split(';', ',', ' ');
                }
                return new string[0];
            }
            set
            {
                SetFieldAttribute("ContentTypes", String.Join(";", value));
            }
        }

        /// <summary>
        /// Gets or sets the scope of the 
        /// </summary>
        public string SearchScope
        {
            get { return GetFieldAttribute("Scope"); }
            set { SetFieldAttribute("Scope", value); }
        }

        /// <summary>
        /// Creates a new LookupPickerField.
        /// </summary>
        /// <param name="fields"></param>
        /// <param name="fieldName"></param>
        public LookupPickerField(SPFieldCollection fields, string fieldName) : base(fields, fieldName) { }

        /// <summary>
        /// Creates a new LookupPickerField.
        /// </summary>
        /// <param name="fields"></param>
        /// <param name="typeName"></param>
        /// <param name="displayName"></param>
        public LookupPickerField(SPFieldCollection fields, string typeName, string displayName) : base(fields, typeName, displayName) { }

        /// <summary>
        /// Returns a <see cref="LookupPickerFieldControl"/> as its rendering control.
        /// </summary>
        public override BaseFieldControl FieldRenderingControl
        {
            get { return new LookupPickerFieldControl() { FieldName = InternalName }; }
        }

        private void SetFieldAttribute(string attribute, string value)
        {
            GetType().BaseType.GetMethod("SetFieldAttributeValue", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(this, new object[] { attribute, value });
        }

        private string GetFieldAttribute(string attribute)
        {
            return GetType().BaseType.GetMethod("GetFieldAttributeValue", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(String) }, null)
                .Invoke(this, new object[] { attribute }) as string ?? "";
        }

        /// <summary>
        /// Returns the value of the field passed with the argument.
        /// </summary>
        /// <param name="value">A string that contains the field value</param>
        /// <returns></returns>
        public override object GetFieldValue(string value)
        {
            try
            {
                return base.GetFieldValue(value);
            }
            catch (Exception)
            {
                return null;
            }
        }

        private string m_dispFormUrl = null;
        
        /// <summary>
        /// Returns the values as links to the displayform of the related items.
        /// </summary>
        /// <remarks>
        /// Overridden to handle items from different webs.
        /// </remarks>
        /// <param name="value"></param>
        /// <returns></returns>
        public override string GetFieldValueAsHtml(object value)
        {
            var result = base.GetFieldValueAsHtml(value);
            if (string.IsNullOrEmpty(result) && !string.IsNullOrEmpty(GetFieldValueAsText(value)))
            {
                if (this.AllowMultipleValues)
                {
                    string str2 = string.Empty;
                    try
                    {
                        SPFieldLookupValueCollection values = new SPFieldLookupValueCollection(value.ToString());
                        if (values == null)
                        {
                            return string.Empty;
                        }
                        if (this.m_dispFormUrl == null)
                        {
                            SPSecurity.SuppressAccessDeniedRedirectInScope scope = new SPSecurity.SuppressAccessDeniedRedirectInScope();
                            try
                            {
                                using (var lookupWeb = this.ParentList.ParentWeb.Site.OpenWeb(this.LookupWebId))
                                {
                                    SPList list = lookupWeb.Lists[this.LookupListId];
                                    this.m_dispFormUrl = list.ParentWeb.Url + "/_layouts/listform.aspx?PageType=4&ListId=" + list.ID.ToString();//.InternalName;
                                }
                            }
                            catch (UnauthorizedAccessException)
                            {
                                this.m_dispFormUrl = string.Empty;
                            }
                            finally
                            {
                                if (scope != null)
                                {
                                    scope.Dispose();
                                }
                            }
                        }
                        if (string.IsNullOrEmpty(this.m_dispFormUrl))
                        {
                            return string.Empty;
                        }
                        StringBuilder builder = new StringBuilder();
                        for (int i = 0; i < values.Count; i++)
                        {
                            if (i > 0)
                            {
                                builder.Append("; ");
                            }
                            StringBuilder builder2 = new StringBuilder();
                            builder2.Append(this.m_dispFormUrl);
                            builder2.Append("&ID=");
                            builder2.Append(values[i].LookupId);
                            builder2.Append("&RootFolder=*");
                            builder.Append("<a ");
                            if ((this.ParentList.ParentWeb.UIVersion > 3) && !SPContext.Current.IsPopUI)
                            {
                                builder.Append("onclick=\"OpenPopUpPage('");
                                builder.Append(builder2);
                                builder.Append("', RefreshPage); return false;\" ");
                            }
                            builder.Append("href=\"");
                            builder.Append(builder2);
                            builder.Append("\">");
                            builder.Append(SPHttpUtility.HtmlEncode(values[i].LookupValue));
                            builder.Append("</a>");
                        }
                        str2 = builder.ToString();
                    }
                    catch (ArgumentException)
                    {
                    }
                    return str2;
                }
                string str = (value is string) ? ((string)value) : Convert.ToString(value, CultureInfo.InvariantCulture);
                return str;
            }
            return result;
        }
    }
}
